package PaperExperiment;

import java.util.*;

import XmlLoader.FGObjProcess;
import XmlLoader.FGObjectTrajectoryStructure;

public class DTW {

	public double DTWdistance(ArrayList<Integer[]> A, ArrayList<Integer[]> B)
	{
		//double K = 0;
		double DTWarr[][] = new double[A.size()+1][B.size()+1];
		double DTWrecord[][] = new double[A.size()+1][B.size()+1];
		for (int i = 1; i <= A.size(); i++)
			DTWarr[i][0] = 200000;
		for (int j = 1; j <= B.size(); j++)
			DTWarr[0][j] = 200000;
		DTWarr[0][0] = 0.0;
		
		
		for (int i = 1; i <= A.size(); i++)
			for (int j = 1; j <= B.size(); j++)
			{
				double cost = distance(A.get(i-1), B.get(j-1));
				double mincost = min3(DTWarr[i-1][j], DTWarr[i][j-1], DTWarr[i-1][j-1]);
				if( mincost == DTWarr[i-1][j])
					DTWrecord[i][j] = 10;
				else if ( mincost == DTWarr[i][j-1])
					DTWrecord[i][j] = 1;
				else
					DTWrecord[i][j] = 11;
				DTWarr[i][j] = cost + mincost;
			}
		int x = A.size(), y = B.size();
		while(x != 0 && y != 0)
		{
			if(DTWrecord[x][y] == 11)
			{
				x--; y--;
			}
			else if(DTWrecord[x][y] == 1)
				y--;
			else
				x--;
			//K += 1;
		}
		
		//return DTWarr[A.size()][B.size()]/(K+(double)x+(double)y);
		return DTWarr[A.size()][B.size()];
	}
	private double distance(Integer[] A, Integer[] B)
	{
		
		return Math.sqrt((A[0].doubleValue()-B[0].doubleValue())*(A[0].doubleValue()-B[0].doubleValue()) + (A[1].doubleValue()-B[1].doubleValue())*(A[1].doubleValue()-B[1].doubleValue()));
	}
	private double min3(double i, double j, double k)
	{
		double min;
		if(i<=j)
			min = i;
		else
			min = j;
		if(min >= k)
			min = k;
		return min;
	}
	
	public static void main(String[] args) {
		long startTimeBuild = System.currentTimeMillis();
		FGObjProcess fgObj = new FGObjProcess(args[1]);
		//training data
		List<String> list_objIndex = fgObj.ACT004_getStringList(args[0]);
		List<FGObjectTrajectoryStructure> list = fgObj.ACT001_getListOfObj(list_objIndex);
		//testing data
		List<String> list_objIndex2 = fgObj.ACT004_getStringList(args[2]);
		List<FGObjectTrajectoryStructure> listTest = fgObj.ACT001_getListOfObj(list_objIndex2);
    	
		System.out.println("Database Load time " + (System.currentTimeMillis() - startTimeBuild));
		long startTimeTest = System.currentTimeMillis();
		
    	DTW dtw = new DTW();
    	
    	double abnormal_threshold = 2.0;
    	
    	for (int i = 0; i<listTest.size();i++)
    	{
    		double total_DTWdis = 0;
    		int size = listTest.get(i).GET002_nNumberOfPoint();
    		ArrayList<Integer[]> X = new ArrayList<Integer[]>();
    		
    		for (int j = 0; j < size; j++) //trajectory point
    		{
    			Integer[] a = {listTest.get(i).GET003_elementIn_list_fGObject(j).GET001_centerReal().x, listTest.get(i).GET003_elementIn_list_fGObject(j).GET001_centerReal().y}; 
    			X.add(a);
    		}
    		//System.out.println("i = "+i);
    		for (int j = 0; j<list.size(); j++) //another trajectory Y
    		{
    			if(i != j)
    			{
    				ArrayList<Integer[]> Y = new ArrayList<Integer[]>();
    				int size2 = list.get(j).GET002_nNumberOfPoint();
    				for (int k = 0; k < size2; k++)
    				{
    					Integer[] a = {list.get(j).GET003_elementIn_list_fGObject(k).GET001_centerReal().x, list.get(j).GET003_elementIn_list_fGObject(k).GET001_centerReal().y}; 
    					Y.add(a);
    				}
    				total_DTWdis += dtw.DTWdistance(X, Y);
    				
    			}
    		}
    		//System.out.println("id = " + i + ":Total distance = " + Math.sqrt(total_DTWdis)/(double)(list.size()-1) );
    		if(Math.sqrt(total_DTWdis)/(double)(list.size()-1) <= abnormal_threshold)
    			System.out.println(true);
    		else
    			System.out.println(false);
    	}
    	System.out.println("Testing time " + (System.currentTimeMillis() - startTimeTest));
	}

}
